#include"definicje.h"
#include<stdio.h>
#include<stdlib.h>
#include<inttypes.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<string.h>
#include<error.h>
#include<sys/select.h>
#include<unistd.h>
#include"protokol.h"

#define PORT "9999"

uint8_t buforbin[MAX_PAKIET];
uint8_t buforhex[MAX_PAKIET*2];

int stworzGniazdoNasluchujace(int *gniazdo)
{
   unsigned int i;
   int wynik;
   struct addrinfo wskazowki;
   struct addrinfo *adresy, *wskaznik;

   memset(&wskazowki, 0, sizeof(struct addrinfo));
   wskazowki.ai_family = AF_INET;
   wskazowki.ai_socktype = SOCK_DGRAM;
   wskazowki.ai_flags = AI_PASSIVE;

   wynik=getaddrinfo(NULL,PORT,&wskazowki,&adresy);
   if(wynik!=0)
   {
      fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(wynik));
      exit(EXIT_FAILURE);
   }
   for(wskaznik = adresy; wskaznik != NULL; wskaznik=wskaznik->ai_next)
   {
      *gniazdo=socket(
	    wskaznik->ai_family,
	    wskaznik->ai_socktype,
	    wskaznik->ai_protocol);
      if(*gniazdo==-1)
      {
	 perror("socket");
	 exit(EXIT_FAILURE);
      }
      wynik=bind(*gniazdo,wskaznik->ai_addr,wskaznik->ai_addrlen);
      if(wynik==-1)
      {
	 close(*gniazdo);
	 perror("bind");
	   continue; /*ERROR*/
      }
      freeaddrinfo(adresy);
      return 0;
   }
   freeaddrinfo(adresy);
   return -1;
}

void hextobin(size_t  ilosc)
{
   unsigned int i,j;
   for(i=0;i<ilosc/2;++i)
   {
      buforbin[i]=0u;
      for(j=0;j<2;++j)
      {
	 buforbin[i]*=16;
	 if(buforhex[2*i+j]>='0' && buforhex[2*i+j]<='9')
	 {
	    buforbin[i]+=buforhex[2*i+j]-'0';
	 }
	 else if(buforhex[2*i+j]>='A' && buforhex[2*i+j]<='F')
	 {
	    buforbin[i]+=buforhex[2*i+j]-'A'+10;
	 }
	 else
	 {
	    exit(EXIT_FAILURE);
	 }
      }
   }
}

void bintohex(size_t ilosc)
{
   unsigned int i;
   for(i=0;i<ilosc;++i)
   {
      if(buforbin[i]/16<10)
      {
	 buforhex[2*i]=buforbin[i]/16+'0';
      }
      else
      {
	 buforhex[2*i]=buforbin[i]/16-10+'A';
      }
      if(buforbin[i]%16<10)
      {
	 buforhex[2*i+1]=buforbin[i]%16+'0';
      }
      else
      {
	 buforhex[2*i+1]=buforbin[i]%16-10+'A';
      }
   }
}


int main(int argc, char *argv[])
{
   int wynik;
   int gniazdo;
   fd_set zbior;
   struct sockaddr_storage adres;
   socklen_t dlugosc;
   size_t licznik=0;
   uint8_t bufor[MAX_PAKIET];
   uint8_t bufor2[MAX_PAKIET];
   ssize_t ile;
   ssize_t ile2;
   unsigned char znak;
   unsigned int i;
   unsigned char znaki[2];

   stworzGniazdoNasluchujace(&gniazdo);

   

start:

   FD_ZERO(&zbior);
   FD_SET(0,&zbior);
   FD_SET(gniazdo,&zbior);
   select(gniazdo+1,&zbior,NULL,NULL,NULL);
   if(FD_ISSET(0,&zbior))
   {
      ile=read(0,&buforhex,MAX_PAKIET);
      if(ile==-1)
      {
	 perror("read");
      }
      hextobin(ile);
      ile2=sendto(gniazdo,buforbin,ile/2,0,(struct sockaddr *)&adres,dlugosc);
      if(ile2==-1)
      {
	 perror("sendto");
	 exit(EXIT_FAILURE);
      }
      if(ile2!=ile/2)
      {
	 fprintf(stderr,"Nie udało się wysłać wszystkich bajtów\n");
      }
   }
   if(FD_ISSET(gniazdo,&zbior))
   {
      dlugosc=sizeof(struct sockaddr_storage);
      ile=recvfrom(gniazdo,buforbin,MAX_PAKIET,0,(struct sockaddr *)&adres,&dlugosc);
      if(ile==-1)
      {
	 perror("recvfrom");
      }
      bintohex(ile);
      ile2=write(1,buforhex,ile*2);
      if(ile2==-1)
      {
	 perror("write");
	 exit(EXIT_FAILURE);
      }
      if(ile2!=ile*2)
      {
	 fprintf(stderr,"Nie udało się wypisać wszystkich bajtów\n");
      }
   }
   goto start;
   return EXIT_SUCCESS;
}
